package com.alibaba.shopping_manager_api.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

/**
 * @ClassName SecurityConfig
 * @Description Security配置类
 * @Author Leo
 * @Date 2024/12/6 19:50
 */
@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {

        // 自定义表单登录策略
        httpSecurity.formLogin(
                form -> {
                    form.usernameParameter("username") // 用户名
                            .passwordParameter("password") // 密码项
                            .loginProcessingUrl("/admin/login") // 登录请求提交路径
                            .successHandler(new MyLoginSuccessHandler()) //登录成功处理器
                            .failureHandler(new MyLoginFailureHandler()); // 登录失败处理器
                }
        );

        // 退出登录的策略
        httpSecurity.logout(
                logout -> {
                    // 用户注销登录状态的请求地址
                    logout.logoutUrl("/admin/logout")
                            // 注销成功的处理器
                            .logoutSuccessHandler(new MyLogoutSuccessHandler())
                            // 请求认证数据
                            .clearAuthentication(true)
                            // 请求session
                            .invalidateHttpSession(true);

                }
        );

        // 定义权限拦截配置
        httpSecurity.authorizeHttpRequests(
                resp -> {
                    // 登录相关的请求不需要进行认证
                    resp.requestMatchers("/login","/admin/login").permitAll();
                    // 其余请求都需要认证成功才能访问
                    resp.anyRequest().authenticated();
                }
        );

        // 异常处理策略
        httpSecurity.exceptionHandling(
                exception -> {
                    // 未登录处理器
                    exception.authenticationEntryPoint(new MyAuthenticationEntryPoint())
                            // 权限不足
                            .accessDeniedHandler(new MyAccessDeniedHandler());
                }
        );
        // 开启跨域访问
        httpSecurity.cors();

        // 关闭csrf防护
        httpSecurity.csrf(csrf -> csrf.disable());
        return httpSecurity.build();
    }

    // 密码加密工具
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}




